package pl.edu.agh.gronoMining.resultAnalyzer.resultNormalizer;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultEdge;

import pl.edu.agh.gronoMining.resultAnalyzer.resultNormalizer.graph.Edge;
import pl.edu.agh.gronoMining.resultAnalyzer.resultNormalizer.graph.Vertex;
import pl.edu.agh.gronoMining.resultAnalyzer.resultNormalizer.parser.GraphParser;
import pl.edu.agh.gronoMining.resultAnalyzer.resultNormalizer.parser.LineParser;

public class Main {

private static final Set<String> possibleArgsSet = new HashSet<String>();
	
	private static final String LOGGER_PROP_FILE = "resources/logger.properties.xml";
	
	private static Logger logger;
	
	static {
		possibleArgsSet.add("file");
		possibleArgsSet.add("outputFile");
	}
	
	private static Properties parseArgs(String[] args) throws ParseException {
		Properties p = new Properties();
		for (String arg : args) {
			String[] argParts = arg.split("=");
			if (argParts.length != 2) {
				throw new ParseException("wrong argument "+arg, 1);
			} else if (argParts[0].charAt(0) != '-') {
				throw new ParseException("wrong argument "+arg, 1);
			} else {
				String key = argParts[0].substring(1);
				String value = argParts[1];
				if (possibleArgsSet.contains(key))
					p.setProperty(key, value);
				else
					throw new ParseException("wrong argument "+arg, 1);
			}
		}
		return p;
	}
	
	private static boolean isSubgraph(Graph<Vertex, Edge> graph, Graph<Vertex, Edge> checkGraph) {
		
		Set<Graph<Vertex, Edge>> possibleGraphs = new HashSet<Graph<Vertex, Edge>>();
		
		Map<Edge,Set<Edge>> edgesMap = new HashMap<Edge,Set<Edge>>();
		//logger.info("=========");
		for (Edge e : graph.edgeSet()) {
			
			int label1 = graph.getEdgeSource(e).getLabel();
			int label2 = graph.getEdgeTarget(e).getLabel();
			//logger.info("ceck edge - "+label1+" - "+label2);
			Set<Edge> possibleEdges = new HashSet<Edge>();
			
			for (Edge checkEdge : checkGraph.edgeSet()) {
				Vertex v1 = checkGraph.getEdgeSource(checkEdge);
				Vertex v2 = checkGraph.getEdgeTarget(checkEdge);
				//logger.info("mabye edge "+v1.getLabel()+"-"+v2.getLabel());
				if ((v1.getLabel() == label1 && v2.getLabel() == label2) ||
						(v1.getLabel() == label2 && v2.getLabel() == label1))
					possibleEdges.add(checkEdge);
			}
			
			if (possibleEdges.size() == 0)
				return false;
			//logger.info("found");
			edgesMap.put(e, possibleEdges);	
		}
		
		//TODO what to do here?
		return true;
		
		//return false;
	}
	
	public static void main(String[] args) throws ParseException, IOException {
		
		DOMConfigurator.configure(LOGGER_PROP_FILE);
		logger = Logger.getLogger(Main.class);
		logger.info("loger inicialized");
		
		Properties prop = parseArgs(args);
		if (! prop.containsKey("outputFile"))
			prop.setProperty("outputFile", prop.getProperty("file")+".normalized");
		
		GraphParser parser = new LineParser();
		
		File graphFile = new File(prop.getProperty("file"));
		File outputFile = new File(prop.getProperty("outputFile"));
		outputFile.createNewFile();
		
		logger.info("try to parse file "+graphFile);
		Graph<Vertex, Edge>[] graphs = parser.parse(graphFile);
		logger.info("parsing complete");
		
		logger.info("before normalizing there is "+graphs.length+" graphs;");
		Set<Graph<Vertex, Edge>> resultSet = new HashSet<Graph<Vertex, Edge>>();
		for (Graph<Vertex, Edge> g : graphs) {
			boolean isOriginal = true;
			for (Graph<Vertex, Edge> checkGraph : graphs) {
				if (g.equals(checkGraph))
					continue;
				if (isSubgraph(g, checkGraph)) {
					isOriginal = false;
					break;
				}	
			}
			if (isOriginal)
				resultSet.add(g);
		}
		
		logger.info("after normalizing there is "+resultSet.size()+" graphs;");
		
		parser.serializeToFile(resultSet, outputFile);
		
		logger.info("result serialized to "+outputFile);
	}
	
}
